package com.hhxyjsj.util;

import java.io.InputStream;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpStatus;

import org.apache.http.HttpResponse;

import org.apache.http.NameValuePair;

import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.params.CookiePolicy;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

import com.hhxyjsj.email.MailUtils;
@SuppressWarnings("unchecked")
public class VClient {
	private static Logger logger = Logger.getLogger(MailUtils.class);

	public HttpClient client=new DefaultHttpClient();
	public final String METHOD_GET="get";
	public final String METHOD_POST="post";
	private String encoding ="gb2312";
	private HttpEntity entity=null;
	private String content="";
	private boolean isgetcontent=false;
	private int statusCode;
	private int repeatCout=5;

	private int _repeatCout=repeatCout;
	
	public int getStatusCode() {
		return statusCode;
	}
	public void setTimeOut(int timeout){
		client.getParams().setIntParameter(HttpConnectionParams.SO_TIMEOUT,timeout);
	}
	
	public void setClientIsNotSafe(){
		try {                        
			SSLContext ctx = SSLContext.getInstance("TLS");                         
			X509TrustManager tm = new X509TrustManager() {                                 
				public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {} 
				public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {}   
				public X509Certificate[] getAcceptedIssuers() {
					return null;                    
				} 
			}; 
			ctx.init(null, new TrustManager[]{tm}, null);   
			SSLSocketFactory ssf = new SSLSocketFactory(ctx);  
			ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);       
			ClientConnectionManager ccm = client.getConnectionManager();        
			SchemeRegistry sr = ccm.getSchemeRegistry();              
			sr.register(new Scheme("https", ssf, 443));            
			new DefaultHttpClient(ccm, client.getParams());     
		} catch (Exception ex) {         
			ex.printStackTrace();	
		} 
	}
	public VClient(){
		client.getParams().setIntParameter(HttpConnectionParams.SO_TIMEOUT,5000); //超时设置
//		client.getHostConfiguration().setHost("http://bcwars.com", 80);
	}
	public VClient(String encoding){
		this.encoding=encoding;
		client.getParams().setIntParameter(HttpConnectionParams.SO_TIMEOUT,5000);
	}
	public VClient(String ip,int port){
		HttpHost proxy = new HttpHost(ip, port);
		client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); 
		client.getParams().setIntParameter(HttpConnectionParams.SO_TIMEOUT,5000);
	}
	public void addProxy(String ip,int port){
		HttpHost proxy = new HttpHost(ip, port,"http");		
		client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); 
	}
	public void removeProxy(){		
		client.getParams().removeParameter(ConnRoutePNames.DEFAULT_PROXY); 
	}
	private void executeMethod(String url,Map<String, Object> params,String method){
		try {
			if(StringUtils.isEmpty(url)){
				throw new Exception("url地址为空");
			}
			if(StringUtils.isEmpty(method)){
				throw new Exception("METHOD方式为空");
			}

			HttpRequestBase httpMethod=null;
			if(METHOD_GET.equals(method)){
				HttpGet get=new HttpGet(url);
				httpMethod=get;
				if (params != null&&params.size()>0) {
					HttpParams httpParams=new BasicHttpParams();	            
					for (Map.Entry<String, Object> entry : params.entrySet()) { 
						String key=entry.getKey();
						Object value=entry.getValue();
						if(value instanceof List){
							List vList=(List)value;
							for (int i = 0; i < vList.size(); i++) {
//								httpParams.setParameter(key+"["+i+"]",value);
								httpParams.setParameter(key,value);
							}
						}else {
							httpParams.setParameter(key,value);
						}
						
					} 
					get.setParams(httpParams);
				} 
			}else if(METHOD_POST.equals(method)){
				HttpPost post=new HttpPost(url);
				httpMethod=post;
				List<NameValuePair> anamevaluepair=new ArrayList<NameValuePair>();	  
				if (params != null&&params.size()>0) {			          
					for (Map.Entry<String, Object> entry : params.entrySet()) { 
						String key=entry.getKey();
						Object value=entry.getValue();
						if(value instanceof List){
							List vList=(List)value;
							for (int i = 0; i < vList.size(); i++) {
//								anamevaluepair.add(new BasicNameValuePair(key+"["+i+"]",(String)vList.get(i)));
								anamevaluepair.add(new BasicNameValuePair(key,(String)vList.get(i)));
							}
						}else {
							anamevaluepair.add(new BasicNameValuePair(key,(String)value));
						}
						
					} 
				}       
				post.setEntity(new UrlEncodedFormEntity(anamevaluepair,encoding));  
			}else{
				throw new Exception("不是有效的METHOD方式");	
			}
			if(entity!=null){
				entity.consumeContent();
				isgetcontent=false;
			}
			statusCode=HttpStatus.SC_BAD_REQUEST;
			Object _proxy=client.getParams().getParameter(ConnRoutePNames.DEFAULT_PROXY);
			if(_proxy!=null&&_proxy instanceof HttpHost){
				HttpHost proxyhost=(HttpHost)_proxy;
				String hostname=proxyhost.getHostName();
				httpMethod.setHeader("HTTP_X_FORWARDED_FOR",hostname);
			}
			HttpClientParams.setCookiePolicy(client.getParams(), CookiePolicy.BROWSER_COMPATIBILITY);  

			HttpResponse response= client.execute(httpMethod);
			entity = response.getEntity(); 
//			HttpParams p=response.getParams();
//			httpMethod.get
			statusCode = response.getStatusLine().getStatusCode();
			if ((statusCode == HttpStatus.SC_MOVED_PERMANENTLY) ||
					(statusCode == HttpStatus.SC_MOVED_TEMPORARILY) ||
					(statusCode == HttpStatus.SC_SEE_OTHER) ||
					(statusCode == HttpStatus.SC_TEMPORARY_REDIRECT)) {
				// 此处重定向处理   此处还未验证
				String newUri = response.getLastHeader("Location").getValue();
				int index;
				if((index = url.lastIndexOf("/")) != -1){
					newUri = url.substring(0, index + 1) + newUri;
				}
				executeMethod(newUri,params,method);
			}
			_repeatCout=repeatCout;
		} catch (Exception e) {
			// TODO: handle exception
			_repeatCout--;
			if(_repeatCout>0){
				 executeMethod(url, params, method);
				 return;
			}
			_repeatCout=repeatCout;
			logger.info(e.toString());
			
		}
	}
	public void close(){
		if(entity!=null){
			try {
				isgetcontent=false;
				entity.consumeContent();
				entity=null;
				client.getConnectionManager().shutdown();
				System.out.println("entity is colse!");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				logger.info(e.toString());
			}			
		}
	}
	public void doPost(String url,Map params){
		executeMethod(url,params,METHOD_POST);
	}

	public void doGet(String url,Map params){
		executeMethod(url,params,METHOD_GET);
	}


	public String getContent(){
		return getContent(false);
	}
	
	//	isfilter是否过滤，只提取html代码中body下的内容，并且取出script，style，iframe，注释
	public String getContent(boolean isfilter){
		try {
			if(!isgetcontent&&entity!=null){
				content=EntityUtils.toString(entity,encoding);
				if(isfilter){
					content=content.replaceAll("&nbsp;|&nbsp", "").replaceAll("&","&amp;").replaceAll("\\r", "").replaceAll("\\t", "").replaceAll("\\n", "####");
					Matcher bodymatcher=Pattern.compile("<body[^>]*>(.*)</body>",Pattern.CASE_INSENSITIVE).matcher(content);
					if(bodymatcher.find()){
						content=bodymatcher.group(1);
					}
					//<!DOCTYPE
					content=Pattern.compile("(<!DOCTYPE[^>]*>)|(<script[^>]*>[ ]*</script>)|(<script[^>]*/>)|(/[\\*]+[^\\*]*[\\*]+/)|(<!--.*?-->)|(<iframe[^>]*>[^<]*</iframe>)|(<style[^>]*>[^<]*</style>)",Pattern.CASE_INSENSITIVE).matcher(content).replaceAll("");
					//&amp;
					//content=Pattern.compile("[\\s]+href[\\s]*=[\\s]*[^\\s^\\>]+",Pattern.CASE_INSENSITIVE).matcher(content).replaceAll(" href=\"#\" ");
					//content=Pattern.compile("[\\s]+src[\\s]*=[\\s]*[^\\s^\\>]+",Pattern.CASE_INSENSITIVE).matcher(content).replaceAll(" src=\"\" ");
					Matcher startmatcher =Pattern.compile("<script[^>]*>",Pattern.CASE_INSENSITIVE).matcher(content);
					Matcher endmatcher =Pattern.compile("</script>",Pattern.CASE_INSENSITIVE).matcher(content);
					StringBuffer newcontent=new StringBuffer();;
					int start=0;
					boolean isend=false;
					while(startmatcher.find()){				
						int _start=startmatcher.start();
						if(_start>start){
							newcontent.append(content.substring(start,_start));
						}				
						if(!endmatcher.find()){
							isend=true;
							break;
						}
						start=endmatcher.end();				
					}
					if(!isend){
						newcontent.append(content.substring(start));
					}
					if(newcontent.length()>0){
						content=newcontent.toString();
					}
					content=content.replaceAll("####", "\n");
				}
//				content=Pattern.compile("(<img[^>]*)/>",Pattern.CASE_INSENSITIVE).matcher(content).replaceAll("$1>");
//				content=Pattern.compile("(<img[^>]*>)",Pattern.CASE_INSENSITIVE).matcher(content).replaceAll("$1</img>");
//				content=Pattern.compile("(<br[^>]*)/>",Pattern.CASE_INSENSITIVE).matcher(content).replaceAll("$1>");
//				content=Pattern.compile("(<br[^>]*>)",Pattern.CASE_INSENSITIVE).matcher(content).replaceAll("$1</br>");
//				content=Pattern.compile("(<li[^>]*>.*?)(<li)",Pattern.CASE_INSENSITIVE).matcher(content).replaceAll("$1</li>$2");
				isgetcontent=true;
//				String cookie="";
//				String split="";
//				List<Cookie> cookies = ((AbstractHttpClient) client).getCookieStore().getCookies();  
//	                   for (Cookie c : cookies)   
//	                 {    
//	                     cookie += split + c.toString();    
//	                    split = ";";    
//	                 }  
//			System.out.println(cookie);  

			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			logger.info(e.toString());
			return "";
		} 
		return content;
	}

	public InputStream getInputStream(){
		try {
			if(!isgetcontent&&entity!=null){				
				isgetcontent=true;
				return entity.getContent();
			}
		} catch (Exception e) {
			logger.info(e.toString());
		}
		return null; 
	}
	public void setRepeatCout(int repeatCout) {
		this.repeatCout = repeatCout;
		_repeatCout=repeatCout;
	}
}
